Android Wear OS DataLayer is not a shared database
I’ve been using the Wear OS DataLayer (now called DataClient) wrong for over a decade – ever since the original Android Wear 4.4W. I always thought it was a shared storage layer where all connected devices got notified whenever data changed. It’s not.
TL;DR: The Wear OS DataLayer is not a global shared database; every node has its own independent storage, and just notifies other nodes when its data changes. I moved to MessageApi to resolve my long-standing synchronization and deletion bugs.
The data sync ping-pong bug
I had a bug ticket in my backlog for 10 years related to data sync between my phone and watch app. Every time the phone’s data changed, it would trigger a sync to the watch, which saved the data locally using shared prefs. This then triggered another sync back to the phone even when the data was identical in the DataLayer and the phone would be notified again. It didn’t impact functionality or cause any UI issues; I just found the Logcat logs annoying.
The real problem began when I extended the shared data and needed to not just save or update data, but also delete it. This started throwing exceptions: the data item was missing a node ID in the path. We don’t need a node ID when saving data, so why is it required for deletion? Because DataLayer isn’t a shared storage; each device has its own. Saving data is permitted within a device’s own storage, but deleting requires explicitly specifying the node ID from which to remove the data. And all this is in the docs ¯\_(ツ)_/¯.
Suddenly, my ping-pong data sync bug made sense. The data was not identical because every phone and watch has its own DataLayer storage; they update independently, and every change is broadcast to all other connected nodes.
To me, this DataLayer behaviour makes no sense. Since every node has its own local storage, why add a complicated API just to do what the SharedPrefs API already does? We already have the MessageApi (now called MessageClient) for notifying other nodes of changes. Instead of building a synchronized storage layer on top of the DataLayer, I removed it entirely and used the MessageApi to sync data between local SharedPrefs. The problems are gone, and I see no reason for DataLayer’s existence.